#include "StaticMeshData.h"
#include "3DSHeader.h"
#include "3DS.h"

//#include <gl\gl.h>										
//#include <gl\glu.h>		

CStaticMeshData::CStaticMeshData(void)
{
}

CStaticMeshData::~CStaticMeshData(void)
{
	Reset();
}

#ifdef CONVERTE_ENABLE
bool CStaticMeshData::CreateFrom3DSData(void* pData)
{
	t3DModel* p3DSData = (t3DModel*)pData;
	if(p3DSData)
	{
		Reset();
		ModelObjects.resize(p3DSData->numOfObjects);

		int iModelObjectsIndex = 0;
		int iModelObjectCount = p3DSData->numOfObjects;

		while(iModelObjectsIndex<iModelObjectCount)
		{
			t3DObject *pObject = &p3DSData->pObject[iModelObjectsIndex];
			if(pObject)
			{
				ModelObjects[iModelObjectsIndex].ResizeBuffers(pObject->numOfFaces*3
															 , pObject->numOfVerts
															 , pObject->numOfVerts
															 , pObject->numTexVertex
																);
				// copy normals
				memcpy(ModelObjects[iModelObjectsIndex].pNormalsBuffer, pObject->pNormals, pObject->numOfVerts*sizeof(D3DXVECTOR3));

				// copy vertex
				memcpy(ModelObjects[iModelObjectsIndex].pVertexBuffer, pObject->pVerts, pObject->numOfVerts*sizeof(D3DXVECTOR3));

				// copy uv
				memcpy(ModelObjects[iModelObjectsIndex].pUVsBuffer, pObject->pTexVerts, pObject->numOfVerts*sizeof(D3DXVECTOR2));

				// copy material info
				ModelObjects[iModelObjectsIndex].MaterialIndex = pObject->materialID;

				// copy vertexindex and uv index
				int iCurIndex =0;
				for(int iFaceIndex=0; iFaceIndex<pObject->numOfFaces; iFaceIndex++)
				{
					memcpy(ModelObjects[iModelObjectsIndex].pVertexIndexBuffer+iCurIndex, pObject->pFaces[iFaceIndex].vertIndex, 3*sizeof(int));
					memcpy(ModelObjects[iModelObjectsIndex].pUVIndexBuffer+iCurIndex, pObject->pFaces[iFaceIndex].coordIndex, 3*sizeof(int));
					iCurIndex += 3;
				}
			}
			iModelObjectsIndex++;
		}

		// copy material info
		for(int i=0; i<p3DSData->numOfMaterials; i++)
		{
			if(strlen(p3DSData->pMaterials[i].strFile)>0)
			{
				std::string TempString = p3DSData->pMaterials[i].strFile;
				TextureList.push_back(TempString);
			}
		}
	}
	return true;
}
#endif


void CStaticMeshData::Reset()
{
	int iModelObjectsIndex = 0;
	int iModelObjectCount = ModelObjects.size();
	while(iModelObjectsIndex<iModelObjectCount)
	{
		ModelObjects[iModelObjectsIndex].Reset();
		iModelObjectsIndex++;
	}
	TextureList.clear();
}


#ifdef CONVERTE_ENABLE
bool CStaticMeshData::DumpToFile(std::string fileName)
{
	FILE* fp = fopen(fileName.c_str(), "wb");
	if(fp)
	{
		// 'SUL' is a flag for my file format
		fwrite("SOUL", 4, 1, fp);

		// write object Count
		int iModelObjectCount = ModelObjects.size();	
		fwrite(&iModelObjectCount, sizeof(iModelObjectCount), 1, fp);

		// write Texture Count
		int iTextureCount = TextureList.size();
		fwrite(&iTextureCount, sizeof(iTextureCount), 1, fp);

		// write Textures
		for(int iTextureIndex=0; iTextureIndex<iTextureCount; iTextureIndex++)
		{
			int iFileNameLength = TextureList[iTextureIndex].length()+1;
			// write fileName length
			fwrite(&iFileNameLength, sizeof(iFileNameLength), 1, fp);
			// write fileName
			fwrite(TextureList[iTextureIndex].c_str(), iFileNameLength, 1, fp);
		}

		// begin write Objs
		int iModelObjectsIndex = 0;
		while(iModelObjectsIndex<iModelObjectCount)
		{
			unsigned int VertexIndexCount_t = ModelObjects[iModelObjectsIndex].VertexIndexCount;
			unsigned int VertexCount_t = ModelObjects[iModelObjectsIndex].VertexCount;
			unsigned int NormalsCount_t = ModelObjects[iModelObjectsIndex].NormalsCount;
			unsigned int UVsCount_t = ModelObjects[iModelObjectsIndex].UVsCount;

			int			MaterialIndex_t = ModelObjects[iModelObjectsIndex].MaterialIndex;

			// write VertexIndexCount
			fwrite(&VertexIndexCount_t, sizeof(VertexIndexCount_t), 1, fp);

			// write VertexCount
			fwrite(&VertexCount_t, sizeof(VertexCount_t), 1, fp);

			// write NormalsCount
			fwrite(&NormalsCount_t, sizeof(VertexCount_t), 1, fp);

			// write UVsCount
			fwrite(&UVsCount_t, sizeof(UVsCount_t), 1, fp);

			// write MaterialIndex
			fwrite(&MaterialIndex_t, sizeof(MaterialIndex_t), 1, fp);

			// write VertexIndex
			fwrite(ModelObjects[iModelObjectsIndex].pVertexIndexBuffer, sizeof(int)*VertexIndexCount_t, 1, fp);

			// write VertexBuffer
			fwrite(ModelObjects[iModelObjectsIndex].pVertexBuffer, sizeof(D3DXVECTOR3)*VertexCount_t, 1, fp);

			// write NormalsBuffer
			fwrite(ModelObjects[iModelObjectsIndex].pNormalsBuffer, sizeof(D3DXVECTOR3)*NormalsCount_t, 1, fp);

			// write UVsBuffer
			fwrite(ModelObjects[iModelObjectsIndex].pUVsBuffer, sizeof(D3DXVECTOR2)*UVsCount_t, 1, fp);

			iModelObjectsIndex++;
		}
		fclose(fp);
	}
	return true;
}
#endif


bool CStaticMeshData::CreateFromFile(std::string fileName)
{
	FILE* fp = fopen(fileName.c_str(), "rb");
	if(fp)
	{
		// 'SUL' is a flag for my file format
		BYTE Flag[4]={'S', 'O', 'U', 'L'};
		BYTE ReadFlag[4];
		fread(ReadFlag, 4, 1, fp);
		if(!memcmp(Flag, ReadFlag, 4*sizeof(BYTE)))
		{
			// read object Count
			int iModelObjectCount = 0;	
			fread(&iModelObjectCount, sizeof(iModelObjectCount), 1, fp);
			if(iModelObjectCount>0)
			{
				ModelObjects.resize(iModelObjectCount);
			}

			// read Texture Count
			int iTextureCount = 0;
			fread(&iTextureCount, sizeof(iTextureCount), 1, fp);

			// read Textures
			for(int iTextureIndex=0; iTextureIndex<iTextureCount; iTextureIndex++)
			{
				int iFileNameLength = 0;
				// read fileName length
				fread(&iFileNameLength, sizeof(iFileNameLength), 1, fp);

				BYTE* pStrBuffer = (BYTE*)malloc(iFileNameLength);
				// read fileName
				fread(pStrBuffer, iFileNameLength, 1, fp);
				std::string TempString;
				TempString = *pStrBuffer;
				TextureList.push_back(TempString);
			}

			// begin read Objs
			int iModelObjectsIndex = 0;
			while(iModelObjectsIndex<iModelObjectCount)
			{
				unsigned int VertexIndexCount_t = 0;
				unsigned int VertexCount_t = 0;
				unsigned int NormalsCount_t = 0;
				unsigned int UVsCount_t = 0;

				int			MaterialIndex_t = 0;

				// write VertexIndexCount
				fread(&VertexIndexCount_t, sizeof(VertexIndexCount_t), 1, fp);

				// write VertexCount
				fread(&VertexCount_t, sizeof(VertexCount_t), 1, fp);

				// write NormalsCount
				fread(&NormalsCount_t, sizeof(VertexCount_t), 1, fp);

				// write UVsCount
				fread(&UVsCount_t, sizeof(UVsCount_t), 1, fp);

				// write MaterialIndex
				fread(&MaterialIndex_t, sizeof(MaterialIndex_t), 1, fp);
				
				// resize buffer
				ModelObjects[iModelObjectsIndex].ResizeBuffers(VertexIndexCount_t
																, VertexCount_t
																, NormalsCount_t
																, UVsCount_t);
				// write VertexIndex
				fread(ModelObjects[iModelObjectsIndex].pVertexIndexBuffer, sizeof(int)*VertexIndexCount_t, 1, fp);

				// write VertexBuffer
				fread(ModelObjects[iModelObjectsIndex].pVertexBuffer, sizeof(Tuple3f)*VertexCount_t, 1, fp);

				// write NormalsBuffer
				fread(ModelObjects[iModelObjectsIndex].pNormalsBuffer, sizeof(Tuple3f)*NormalsCount_t, 1, fp);

				// write UVsBuffer
				fread(ModelObjects[iModelObjectsIndex].pUVsBuffer, sizeof(Tuple2f)*UVsCount_t, 1, fp);

				// assign material ID
				ModelObjects[iModelObjectsIndex].MaterialIndex = MaterialIndex_t;

				iModelObjectsIndex++;
			}

			// 
		}
		else
		{
			// not sul file
			return FALSE;
		}
		fclose(fp);
	}
	else
	{
		return FALSE;
	}
	return TRUE;
}
#ifdef CONVERTE_ENABLE
void CStaticMeshData::Render()
{
	int iModelObjectIndex = 0;
	int iModelObjectCount = ModelObjects.size();
	while(iModelObjectIndex<iModelObjectCount)
	{
		int iVertexIndexIndex = 0;
		int iVertexIndexCount = ModelObjects[iModelObjectIndex].VertexIndexCount;
		glColor3ub(255, 255, 255);
		glBegin(GL_TRIANGLES);
		while(iVertexIndexIndex<iVertexIndexCount)
		{
			int* pTriangleIndex = &ModelObjects[iModelObjectIndex].pVertexIndexBuffer[iVertexIndexIndex];
			glNormal3fv((float*)&ModelObjects[iModelObjectIndex].pNormalsBuffer[*pTriangleIndex]);
			glVertex3fv((float*)&ModelObjects[iModelObjectIndex].pVertexBuffer[*pTriangleIndex]);

			glNormal3fv((float*)&ModelObjects[iModelObjectIndex].pNormalsBuffer[*(pTriangleIndex+1)]);
			glVertex3fv((float*)&ModelObjects[iModelObjectIndex].pVertexBuffer[*(pTriangleIndex+1)]);

			glNormal3fv((float*)&ModelObjects[iModelObjectIndex].pNormalsBuffer[*(pTriangleIndex+2)]);
			glVertex3fv((float*)&ModelObjects[iModelObjectIndex].pVertexBuffer[*(pTriangleIndex+2)]);
			iVertexIndexIndex+=3;
		}
		glEnd();

		iModelObjectIndex++;
	}
}
#endif